﻿using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using System.Xml;
using System.Collections;

public class FightLogic : MonoBehaviour
{
	private ModelLocator model;
	/// <summary>
	/// 存放战斗中的对象
	/// </summary>
	private List<GameObject> objList = new List<GameObject> ();

	/// <summary>
	/// 战报信息
	/// </summary>
	private AttackVo attackVo;

	/// <summary>
	/// 战斗初始化基本信息
	/// </summary>
	private List<FightInfoVo> fightInfoList;

	/// <summary>
	/// 战斗回合信息
	/// </summary>
	private List<BoutVo> boutVos;

	/// <summary>
	/// 战斗一个回合的流程信息
	/// </summary>
	private List<FlowVo> _flowVos;

	/// <summary>
	/// 战斗场景
	/// </summary>
	private GameObject fightScene;

	public FightLogic ()
	{
	}

	void Awake ()
	{
		model = ModelLocator.getInstance ();
		MySocket.getInstance ().addEventListener ((int)SystemMsgFlag.NetMessageSC.NM_SC_BATTLE_PVE_ACK, receiveFightReport);
	}
	
	void OnDestroy ()
	{
		MySocket.getInstance ().removeEventListener ((int)SystemMsgFlag.NetMessageSC.NM_SC_BATTLE_PVE_ACK);
	}
	
	public void receiveFight ()
	{
		/*
		XmlDocument xmlDoc = new XmlDocument ();
		string path = Application.dataPath + "/Resources/XmlFiles/FightSS.xml";
		xmlDoc.Load(path);

		attackVo = new AttackVo (xmlDoc);
		fightInfoList = attackVo.fightVos;
		boutVos = attackVo.boutVos;
		
		if (fightScene == null) {
			fightScene = new GameObject ("fightScene");
			Camera main = Camera.main;
			fightScene.transform.parent = main.transform;
			fightScene.transform.localPosition = Vector3.zero;
			fightScene.transform.localScale = Vector3.one;
		}

		LoadSkill ();//可改协同//

		initFightScene ();

		//startFight ();
		*/
	}
	

	/// <summary>
	/// 接收战报
	/// </summary>
	private void receiveFightReport (object o, DispatchEventArgs e)
	{
		ByteArrayEx fightByteArr = new ByteArrayEx ((byte[])e.data [0]);
		string fightStr = fightByteArr.readMultiByteEx ();

		XmlDocument xmlDoc = new XmlDocument ();
		xmlDoc.LoadXml (fightStr);

		attackVo = new AttackVo (xmlDoc);
		fightInfoList = attackVo.fightVos;
		boutVos = attackVo.boutVos;
		
		if (fightScene == null) {
			fightScene = new GameObject ("fightScene");
			Camera main = Camera.main;
			fightScene.transform.parent = main.transform;
			fightScene.transform.localPosition = Vector3.zero;
			fightScene.transform.localScale = Vector3.one;
		}

		LoadSkill ();//可改协同//

		initFightScene ();

		//startFight ();
	}

	/// <summary>
	/// 加载技能资源到制定位置，对应指定名称战斗中使用
	/// </summary>
	private void LoadSkill ()
	{
		List<string> skill = new List<string> ();//存放这场战斗的所有技能名//
		foreach (FightInfoVo fightInfo in fightInfoList) {
			if (!skill.Contains (fightInfo.skill)) {
				skill.Add (fightInfo.skill);
			}
		}

		foreach (BoutVo boutVo in boutVos) {
			foreach (FlowVo flowVo in boutVo.flowVos) {
				if (skill.IndexOf (flowVo.skill) == -1)
					skill.Add (flowVo.skill);
			}
		}

		//..加载资源,初始化到场景..//
		GameObject skillParent = new GameObject ("SkillParent");
		skillParent.transform.parent = fightScene.transform;
		skillParent.transform.localPosition = Vector3.zero;
		skillParent.transform.localScale = Vector3.one;
		foreach (string skillName in skill) {
			if (skillName == "0")
				continue;
			string[] effects = SqliteReader.getInstance ().getIniVal ("Skill", "SkillID", skillName, false, new string[]{"Effect0","Effect1","Effect2","Effect3"});
			for (int i = 0; i < effects.Length; i++) {
				//判断有几个特效//
				if (effects [i] != "0") {
					string effectName = SqliteReader.getInstance ().getIniVal ("SpecialEffect", "EffectID", effects [i], false, new string[]{"ResName"}) [0];
					GameObject skillEffect = (GameObject)Instantiate (Resources.Load (ResPath.SKILLEFFECTFILE + effectName));
					skillEffect.transform.parent = skillParent.transform;
					skillEffect.transform.localScale = Vector3.one;
					skillEffect.name = effectName;
					EffectManagement.GetInstance ().AddIntoPlayList (effects [i], skillEffect);
				}
			}
		}
	}

	/// <summary>
	/// 初始化战斗场景
	/// </summary>
	private void initFightScene ()
	{
		for (int i = 0; i < fightInfoList.Count; i++) {
			
			FightInfoVo fightInfo = fightInfoList [i];
			
			GameObject fightObject = (GameObject)Instantiate (Resources.Load (ResPath.GENERALFILE + GameDefine.FIGHT_MODEL));
			
			fightObject.tag = fightInfo.pos.ToString ();
			fightObject.transform.parent = fightScene.transform;
			fightObject.transform.localPosition = EncounterToFight.GetInstance () [fightInfo.pos];
			fightObject.transform.localScale = Vector3.one;
			
			string[] infos = null;
			
			int tType = fightInfo.type;
			string configId = fightInfo.configID;
			if (tType == (int)GameDefine.GameObjectType.GAMEOBJECT_PLAYER) {
				infos = SqliteReader.getInstance ().getIniVal ("RoleInfo", "RoleID", configId, false, new string[]{"ModelName","FrameSpeed","TopPoint",
					"ColliderPosX","ColliderPosY","ColliderScaleX","ColliderScaleY","ShadowPosX","ShadowPosY","ShadowScaleX","ShadowScaleY"});
			} else if (tType == (int)GameDefine.GameObjectType.GAMEOBJECT_PARTNER) {
				infos = SqliteReader.getInstance ().getIniVal ("Partner", "PartnerID", configId, false, new string[]{"ModelName","FrameSpeed","TopPoint",
					"ColliderPosX","ColliderPosY","ColliderScaleX","ColliderScaleY","ShadowPosX","ShadowPosY","ShadowScaleX","ShadowScaleY"});
			} else if (tType == (int)GameDefine.GameObjectType.GAMEOBJECT_MONSTER) {
				infos = SqliteReader.getInstance ().getIniVal ("MonsterNpc", "MonsterID", configId, false, new string[]{"Model","FrameSpeed","TopPoint",
					"ColliderPosX","ColliderPosY","ColliderScaleX","ColliderScaleY","ShadowPosX","ShadowPosY","ShadowScaleX","ShadowScaleY"});
			}
			
			FightAction tFightAction = fightObject.GetComponent<FightAction> ();
			//model//
			tFightAction.ClipAni.filePath = infos [0];
			int frameSpeed = int.Parse (infos [1]);
			tFightAction.ClipAni.FPS = frameSpeed;
			tFightAction.ClipAni.Play (GameDefine.PROFILEIDLE_ANISTR);
			if (fightObject.transform.localPosition.x > 0) {
				Transform aniLayer = tFightAction.ClipAni.transform;
				aniLayer.localEulerAngles = new Vector3 (0, 180, 0);
			}
			
			//TopPoint//
			Vector3 topPoint = new Vector3 (0, float.Parse (infos [2]), 0);
			tFightAction.TopPoint = topPoint;
			
			//名字的信息//
			UILabel nameLabel = fightObject.transform.Find ("PlayerName").GetComponent<UILabel> ();
			
			nameLabel.text = fightInfo.name;
			nameLabel.transform.localPosition = topPoint + Vector3.up * 10;
			
			//碰撞体信息//
			BoxCollider collider = fightObject.GetComponent<BoxCollider> ();
			if (collider != null) {
				Vector3 boxPos = Vector3.zero;
				boxPos.x = float.Parse (infos [3]);
				boxPos.y = float.Parse (infos [4]);
				collider.center = boxPos;
				Vector3 boxScale = Vector3.one;
				boxScale.x = float.Parse (infos [5]);
				boxScale.y = float.Parse (infos [6]);
				collider.size = boxScale;
			}
			
			//Shadow的信息//
			Transform shadow = fightObject.transform.Find ("Shadow");
			if (shadow != null) {
				Vector3 shadowPos = Vector3.one;
				shadowPos.x = float.Parse (infos [7]);
				shadowPos.y = float.Parse (infos [8]);
				shadow.localPosition = shadowPos;
				Vector3 shadowScale = Vector3.one;
				shadowScale.x = float.Parse (infos [9]);
				shadowScale.y = float.Parse (infos [10]);
				shadow.localScale = shadowScale;
			}
			
			objList.Add (fightObject);
		}

	}

	/// <summary>
	/// 开始战斗
	/// </summary>
	public void startFight ()
	{
		startBout ();
	}
	
	public void FightInterface ()
	{
		fightControl ();
		
		//startBout();
	}

	/// <summary>
	/// 开始新的回合
	/// </summary>
	private void startBout ()
	{
		BoutVo boutVo = boutVos [0];
		_flowVos = boutVo.flowVos;
		boutVos.RemoveAt (0);

		string strCount = boutVo.count.ToString ();//回合数//
		//显示"第xx回合"//
		//showBountNum(strCount);//

		resetPlayerInfo (boutVo.boutInfoVos);

		onUpdateAttackDepth ();
		
		fightControl ();
	}

	/// <summary>
	/// 初始化每回合的战斗对象基本信息
	/// </summary>
	private void resetPlayerInfo (List<BoutInfo> boutInfos)
	{
		foreach (BoutInfo boutInfo in boutInfos) {
			GameObject fightObj = getAttackPlayerFromPos (boutInfo.pos);//每个战斗对象的//

			if (fightObj != null && fightObj.activeSelf) {
				
				FightAction tFightAction = fightObj.GetComponent<FightAction> ();
				
				//重置血量//
				tFightAction.ResetHp (boutInfo.hp, boutInfo.maxhp);
				
				//重置气势//
				tFightAction.ResetMomentum (boutInfo.mor, boutInfo.mor);
				
				//显示此回合buff效果//
				tFightAction.ShowBuffer (boutInfo.buffer);
			}

		}
	}

	/// <summary>
	/// 深度排序
	/// </summary>
	private void onUpdateAttackDepth ()
	{
		GameObject[] arrObj = objList.ToArray ();
		arrObj = BubbleSort (arrObj);

		float indexStartVal = 0;

		foreach (GameObject obj in arrObj) {
			if(obj == null) continue;
			Vector3 pos = obj.transform.localPosition;
			obj.transform.localPosition = new Vector3 (pos.x, pos.y, indexStartVal);
			indexStartVal += 0.001f;
		}

	}

	private GameObject[] BubbleSort (GameObject[] list)
	{
		int i;
		GameObject temp;
		for (int j = 0; j < list.Length; j++) {
			for (i = list.Length - 1; i > j; i--) {
				if(list[j] == null || list[i] == null) continue;
				if (list [j].transform.localPosition.y > list [i].transform.localPosition.y) {
					temp = list [j];
					list [j] = list [i];
					list [i] = temp;
				}
			}
		}
		return list;
	}

	/// <summary>
	/// 战斗流程控制
	/// </summary>
	private void fightControl ()
	{
		if (0 >= _flowVos.Count) {
			//说明要新回合了//
			if (0 == attackVo.boutVos.Count) {
				fightOver ();//战斗结束//
			} else {
				startBout ();
			}
		} else {
			startFlow ();
		}
	}

	/// <summary>
	/// 开始单个回合的战斗流程
	/// </summary>
	private void startFlow ()
	{
		FlowVo flow = _flowVos [0];
		_flowVos.RemoveAt (0);

		//此流程中无伤害数据则跳过//
		if (flow.damageVos.Count == 0) {
			fightControl ();
			return;
		}

		AttackActionVo attackActionVo = new AttackActionVo (flow);//攻击行为数据//

		//施法者//
		GameObject fPlayer = getAttackPlayerFromPos (flow.attackPos);
		
		//目标者数组//
		List<GameObject> tPlayersArr = new List<GameObject> ();

		for (int i = 0; i < flow.damageVos.Count; i++) {
			tPlayersArr.Add (getAttackPlayerFromPos (flow.damageVos [i].targetPos));
		}
		
		FightAction tFightAction = fPlayer.GetComponent<FightAction> ();

		if (attackActionVo.skillAttackType == 5) {//区分技能攻击还是普通攻击(技能需要展示技能名称)//
			//showSkillEffectName(attackActionVo.skill);//显示"xxx技能"//
		}

		//根据不同技能类型实现对应显示逻辑//
		//PlayerFightAction.OnNormalAttack;PlayerFightAction.OnSkillAttack;PlayerFightAction.OnGroupAttack;//
		
		tFightAction.damageVos = flow.damageVos;
		
		
		
		switch (attackActionVo.flag) {
		//普通远程单体攻击//
		case "010":
			tFightAction.DirectNormalAttack (tPlayersArr [0], flow.skill);
			break;
		//普通近程单体攻击//
		case "000":
			tFightAction.SingleNormalNearAttack (tPlayersArr [0], flow.skill);
			break;
		//技能远程单体攻击//
		case "110":
			tFightAction.DirectSkillAttack (tPlayersArr [0], flow.skill);
			break;
		//技能远程群体攻击//
		case "111":
			tFightAction.GroupFarSkillAttack (tPlayersArr.ToArray (), flow.skill);
			break;
		//技能近程单体攻击//
		case "100":
			tFightAction.GroupNearSkillAttack (tPlayersArr.ToArray (), flow.skill);
			break;
		//技能近程群体攻击//
		case "101":
			tFightAction.GroupNearSkillAttack (tPlayersArr.ToArray (), flow.skill);
			break;
		}
		
		
	}

	/// <summary>
	/// 战斗结束
	/// </summary>
	private void fightOver ()
	{
		//model.dispacthEvent();//派发战斗结束,接收后处理//
		//释放资源//
		Destroy (fightScene);
		
		objList.Clear ();
		
		EffectManagement.GetInstance ().ClearPlayList ();
		
		EncounterToFight.GetInstance ().SwitchToEncounter ();
	}
	
	public void RemoveObj(GameObject go){
		objList.Remove(go);
	}



	/// <summary>
	/// 按位置取战斗对象
	/// </summary>
	private GameObject getAttackPlayerFromPos (int pos)
	{
		foreach (GameObject obj in objList) {
			if (obj.tag == pos.ToString ()) {
				return obj;
			}
		}
		return null;
	}
}